package cn.virens.common.spring.annotations.spel;

import cn.virens.common.util.core.Assert;
import cn.virens.common.util.core.objcet.ObjectUtil;
import cn.virens.common.util.exception.APIException;
import org.aopalliance.intercept.MethodInvocation;
import org.dromara.hutool.core.array.ArrayUtil;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.lang.reflect.Method;

public abstract class VirAnnotationEvaluationContext extends StandardEvaluationContext {
    protected final AnnotationAttributes attributes;
    protected Object result;

    protected VirAnnotationEvaluationContext(MethodInvocation invocation, AnnotationAttributes attributes) {
        this.setArguments(Assert.isNull(invocation).getArguments());
        this.setMethod(Assert.isNull(invocation).getMethod());
        this.setClass(Assert.isNull(invocation).getClass());

        this.attributes = Assert.isNull(attributes);
    }

    /**
     * 调用SpringEL对表达式进行解析
     */
    public <R> R parse(ExpressionParser parser, String el, Class<R> clazz) {
        return parser.parseExpression(el).getValue(this, clazz);
    }

    /**
     * 设置请求参数
     */
    protected VirAnnotationEvaluationContext setArguments(Object[] arguments) throws APIException {
        for (int i = 0; i < ArrayUtil.length(arguments); i++) {
            this.setVariable("a" + i, a(arguments, i));
            this.setVariable("p" + i, p(arguments, i));
        }

        return this;
    }

    /**
     * 设置请求方法
     */
    protected VirAnnotationEvaluationContext setMethod(Method method) throws APIException {
        this.setVariable("method", method.getName());

        return this;
    }

    /**
     * 设置请求实体
     */
    protected VirAnnotationEvaluationContext setClass(Class<?> clazz) throws APIException {
        this.setVariable("class", clazz.getSimpleName());

        return this;
    }

    /**
     * 设置执行返回值
     */
    public VirAnnotationEvaluationContext setResult(Object result) throws APIException {
        this.setVariable("result", this.result = result);

        return this;
    }

    protected static Object p(Object[] arguments, int i) {
        return arguments[i];
    }

    protected static Object a(Object[] arguments, int i) {
        return ObjectUtil.toString(arguments[i]);
    }

    /**
     * 获取返回值
     */
    public Object getResult() {
        return result;
    }

}
